/*
 * MIT License
 *
 * Copyright (c) 2024 恩爸编程
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.enba.boot.jwt;

import com.enba.boot.jwt.properties.JwtProperties;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.PrematureJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class JwtHelper {

  private final JwtProperties jwtProperties;

  public JwtHelper(JwtProperties jwtProperties) {
    this.jwtProperties = jwtProperties;
  }

  /**
   * 生成token过期时间
   *
   * @return Date
   */
  private Date expiration() {
    // 设置当前时间和过期时间
    Date now = new Date();
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(now);
    calendar.add(Calendar.MINUTE, jwtProperties.getExpirationMs());
    return calendar.getTime();
  }

  /**
   * 设置“不早于”时间
   *
   * @return Date
   */
  private Date notBefore() {

    Date now = new Date();
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(now);
    calendar.add(Calendar.MINUTE, jwtProperties.getNotBeforeMs());
    return calendar.getTime();
  }

  /**
   * 生成token
   *
   * @param claims 用户信息
   * @return String
   */
  public String createToken(Map<String, Object> claims) {
    return Jwts.builder()
        .setClaims(claims)
        .setIssuedAt(new Date())
        .setNotBefore(notBefore())
        .setExpiration(expiration())
        .signWith(SignatureAlgorithm.HS512, jwtProperties.getSecretKey())
        .compact();
  }

  /**
   * 解析token
   *
   * @param token token
   * @return Claims
   */
  public Claims parseToken(String token) {
    return Jwts.parser()
        .setSigningKey(jwtProperties.getSecretKey())
        .parseClaimsJws(token)
        .getBody();
  }

  /**
   * 校验token是否过期
   *
   * @param token token
   * @return boolean
   */
  public boolean validateToken(String token) {
    try {
      parseToken(token);
      return true;
    } catch (ExpiredJwtException e) {
      log.error("jwt Expired error ==> {}", e.getMessage(), e);
      return false;
    } catch (PrematureJwtException e) {
      log.error("jwt Premature error ==> {}", e.getMessage(), e);
      return false;
    } catch (Exception e) {
      log.error("jwt validateToken error ==> {}", e.getMessage(), e);
      return false;
    }
  }
}
